#include "execution/catalog.h"
#include "storage/buffer_pool.h"
#include "storage/disk_manager.h"
#include <cassert>
#include <iostream>
#include <string>
#include <memory>

void testCatalogTableOperations() {
    std::unique_ptr<DiskManager> diskManager = std::make_unique<DiskManager>("test_catalog.db");
    std::unique_ptr<BufferPool> bufferPool = std::make_unique<BufferPool>(10, std::move(diskManager));
    std::remove("catalog.dat");
    std::shared_ptr<Catalog> catalog = std::make_shared<Catalog>(std::move(bufferPool));
    
    TableInfo tableInfo;
    tableInfo.name = "test_table";
    
    ColumnInfo column1;
    column1.name = "id";
    column1.type = "INT";
    column1.length = sizeof(int);
    
    ColumnInfo column2;
    column2.name = "name";
    column2.type = "VARCHAR";
    column2.length = 255;
    
    tableInfo.columns.push_back(column1);
    tableInfo.columns.push_back(column2);
    tableInfo.firstPageId = 0;
    
    bool createResult = catalog->createTable(tableInfo);
    assert(createResult);
    
    TableInfo* savedTableInfo = catalog->getTable("test_table");
    assert(savedTableInfo != nullptr);
    assert(savedTableInfo->name == "test_table");
    assert(savedTableInfo->columns.size() == 2);
    
    std::cout << "testCatalogTableOperations passed!" << std::endl;
}

void testCatalogPersistence() {
    std::unique_ptr<DiskManager> diskManager1 = std::make_unique<DiskManager>("test_catalog.db");
    std::unique_ptr<BufferPool> bufferPool1 = std::make_unique<BufferPool>(10, std::move(diskManager1));
    std::remove("catalog.dat");
    
    {
        std::shared_ptr<Catalog> catalog1 = std::make_shared<Catalog>(std::move(bufferPool1));
        
        TableInfo tableInfo;
        tableInfo.name = "persistent_table";
        
        ColumnInfo column1;
        column1.name = "id";
        column1.type = "INT";
        column1.length = sizeof(int);
        
        ColumnInfo column2;
        column2.name = "name";
        column2.type = "VARCHAR";
        column2.length = 255;
        
        tableInfo.columns.push_back(column1);
        tableInfo.columns.push_back(column2);
        tableInfo.firstPageId = 0;
        
        catalog1->createTable(tableInfo);
        catalog1->saveToStorage();
    }
    
    std::unique_ptr<DiskManager> diskManager2 = std::make_unique<DiskManager>("test_catalog.db");
    std::unique_ptr<BufferPool> bufferPool2 = std::make_unique<BufferPool>(10, std::move(diskManager2));
    
    std::shared_ptr<Catalog> catalog2 = std::make_shared<Catalog>(std::move(bufferPool2));
    catalog2->loadFromStorage();
    
    TableInfo* tableInfo = catalog2->getTable("persistent_table");
    assert(tableInfo != nullptr);
    assert(tableInfo->name == "persistent_table");
    
    std::cout << "testCatalogPersistence passed!" << std::endl;
}

int main() {
    std::cout << "Running Catalog unit tests..." << std::endl;
    
    testCatalogTableOperations();
    testCatalogPersistence();
    
    std::remove("test_catalog.db");
    std::remove("catalog.dat");
    
    std::cout << "All Catalog unit tests passed!" << std::endl;
    return 0;
}